﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

using mvcForum.Core;

using mvcForum.Web.Extensions;
using mvcForum.Core.Abstractions.Interfaces;
using mvcForum.Core.Configuration;

namespace mvcForum.Web.ViewModels {

	public class TopicViewModel : ForumViewModelBase {

		public TopicViewModel(Topic topic, IEnumerable<MessageViewModel> posts, Int32 postsCount, Int32 postsPerPage, Boolean showDeleted, Boolean allowQuickReply, AdminAuthorNameSetting authorSetting) {
			this.Id = topic.Id;
			this.ForumId = topic.Forum.Id;
			this.Title = topic.Title;
			this.Author = topic.Author.AuthorName(authorSetting);
			this.Views = topic.ViewCount;
			this.MessageCount = postsCount;
			this.PerPageCount = postsPerPage;
			// The topic actually also counts as a post (when determining # of pages).
			this.Pages = (int)Math.Ceiling((Decimal)(this.MessageCount + 1) / (Decimal)this.PerPageCount);
			this.Posted = topic.Posted;
			this.AuthorId = topic.Author.Id;

			if (topic.LastPostAuthor != null) {
				this.LastPosted = topic.LastPosted;
				this.LastPostUserId = topic.LastPostAuthor.Id;
				this.LastUsername = topic.LastPostAuthor.AuthorName(authorSetting);
			}

			this.Moved = topic.Flag == TopicFlag.Moved;
			this.Sticky = topic.Sticky;
			this.Announcement = topic.Announcement;
			this.Deleted = (topic.Flag & TopicFlag.Deleted) != 0;
			this.Quarantined = (topic.Flag & TopicFlag.Quarantined) != 0;
			this.Locked = (topic.Flag & TopicFlag.Locked) != 0;

			this.HasUnread = (this.Authenticated
								? (topic.LastPostAuthor == null && topic.AuthorId != this.CurrentUser.Id && topic.LastRead() < topic.Posted)
									|| (topic.LastPostAuthor != null && topic.LastPostAuthorId != this.CurrentUser.Id && topic.LastRead() < topic.LastPosted)
								: false);

			this.Access = topic.Forum.GetAccess();

			this.Following = topic.Following();
			this.ShowDeleted = showDeleted;
			this.AllowQuickReply = allowQuickReply;

			this.Posts = posts;

			if (this.Moved && topic.OriginalTopic != null) {
				this.OriginalTopic = new TopicViewModel(topic.OriginalTopic, new List<MessageViewModel>(), 0, postsPerPage, false, allowQuickReply, authorSetting);
			}

			this.CustomProperties = topic.GetCustomProperties();
		}

		public TopicViewModel OriginalTopic { private set; get; }

		// TODO: Use this!
		public PagingModel Paging { get; set; }

		private AccessFlag Access { get; set; }
		/// <summary>
		/// Is the current user a moderator?
		/// </summary>
		public Boolean IsModerator {
			get {
				return this.HasAccess(AccessFlag.Moderator);
			}
		}

		/// <summary>
		/// Can the current user upload a file?
		/// </summary>
		public Boolean CanUpload {
			get {
				return this.HasAccess(AccessFlag.Upload);
			}
		}

		/// <summary>
		/// Can the current user post?
		/// </summary>
		public Boolean CanPost {
			get {
				return this.HasAccess(AccessFlag.Post);
			}
		}

		public Boolean Moved { get; private set; }
		public Boolean Deleted { get; private set; }
		public Boolean Locked { get; private set; }
		public Boolean Quarantined { get; private set; }

		private Boolean HasAccess(AccessFlag flag) {
			return (this.Access & flag) == flag;
		}

		public IEnumerable<MessageViewModel> Posts { get; private set; }

		public Int32 Id { get; private set; }
		public Int32 ForumId { get; private set; }
		public String Title { get; private set; }
		public String Author { get; private set; }
		public Int32 AuthorId { get; private set; }
		public DateTime Posted { get; private set; }
		public Int32 Views { get; private set; }
		public Int32 MessageCount { get; private set; }
		public DateTime? LastPosted { get; private set; }
		public String LastUsername { get; private set; }
		public Int32? LastPostUserId { get; private set; }

		public Boolean HasUnread { get; private set; }
		public Boolean Sticky { get; private set; }
		public Boolean Announcement { get; private set; }

		public Boolean ShowDeleted { get; private set; }
		public Boolean AllowQuickReply { get; private set; }

		public Int32 PerPageCount { get; private set; }
		public Int32 Page { get; set; }
		public Int32 Pages { get; private set; }

		public Boolean Following { get; private set; }

		public IDictionary<String, String> CustomProperties { get; private set; }
	}
}